package cn.flying.cloud.flow.web;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Map;

import org.apache.commons.beanutils.BeanUtils;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import cn.flying.cloud.base.common.utils.Ft;
import cn.flying.cloud.base.common.vo.Rt;
import cn.flying.cloud.flow.audit.context.FlowControllerContext;
import cn.flying.cloud.flow.audit.controller.BaseFlowAuditController;
import cn.flying.cloud.flow.model.FlowTaskVo;
import cn.flying.cloud.flow.view.ForwardViewStrategy;
import cn.flying.cloud.flow.view.context.ForwardViewStrategyContext;

/**
 * 流程工作台请求处理服务
 *
 * @author: admin
 * @date: 2025年06月21日 23:20
 * @version: 1.0
 */
@Controller
@RequestMapping("/flow")
public class FlowWorkbenchController {

    @Resource
    private ForwardViewStrategyContext strategyContext;
    @Resource
    private FlowControllerContext controllerContext;

    /**
     * 跳转到审批页面
     *
     * @param appNo
     * @param procInstId
     * @return
     */
    @RequestMapping("turn/view")
    public String turnView(String appNo, String procInstId, String key) {
        ForwardViewStrategy strategy = strategyContext.getBean(key);
        return strategy.turnView(appNo, procInstId);
    }

    /**
     * 流程审核提交
     *
     * @param request
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/workbench/audit", method = RequestMethod.POST)
    @ResponseBody
    public Rt<?> submit(HttpServletRequest request) throws Exception {
        // 1、根据传入的提交参数提取当前产品编码或者是流程key
        // 2、根据产品编码或者流程key获取对应的处理控制器（@TaskController标注的bean）
        // 3、根据参数taskDefKey查找对应的method
        // 4、反射方式执行方法
        // 5、响应请求

        String key = request.getParameter("procDefKey");
        String taskDefKey = request.getParameter("taskDefKey");
        if (Ft.String.isBlank(key) || Ft.String.isBlank(taskDefKey)) {
            return Rt.error("请求参数异常！");
        }
        BaseFlowAuditController bean = controllerContext.getBean(key);
        Method method = bean.getMethod(taskDefKey);
        FlowTaskVo<?> taskVo = new FlowTaskVo<>();
        handRequestParam(request, taskVo, method);

        return (Rt<?>) method.invoke(bean, taskVo);
//        return (Rt<?>) ReflectionUtils.invokeMethod(method, bean, taskVo);
    }

    private void handRequestParam(HttpServletRequest request, FlowTaskVo<?> taskVo, Method method) throws InstantiationException, IllegalAccessException, InvocationTargetException {
        //获农方法的参数列表，只有一个参数CommonTaskInfoVo
        Type genericParameterType = method.getGenericParameterTypes()[0];
        Object extInfoV0 = null;
        // 这里做个判断，日的是部分清求提交不需要价展这期
        if (genericParameterType instanceof ParameterizedType) {
            //获取参数的泛化类型
            ParameterizedType parameterizedType = (ParameterizedType) genericParameterType;
            //获取泛化的实际参数类型
            Type actualTypeArgument = parameterizedType.getActualTypeArguments()[0];
            //泛型参数类型
            Class<?> aClass = (Class<?>) actualTypeArgument;
            //实例化
            extInfoV0 = (aClass).newInstance();
            //获取泛型类声明的属性列表
            Field[] fields = extInfoV0.getClass().getDeclaredFields();
            // 遍历属性列表，set请求传入的值
            for (Field field : fields) {
//                if (field.getType().equals(BigDecimal.class) && StringUtils.isBlank(request.getParameter(field.getName()))) {
//                    continue;
//                }
                setProperty(extInfoV0, field, request.getParameter(field.getName()));
            }
        }

        //获取CommonTaskInfoV0声明的属性列表
        Field[] fields = taskVo.getClass().getDeclaredFields();
        //遍历列表，set请求传入的参数值
        for (Field field : fields) {
            if ("extData".equals(field.getName()) && extInfoV0 != null) {
                //extData表示是扩展的参数，CommonTaskInfoV0的泛型类型，没有泛型就不要赋值
                BeanUtils.setProperty(taskVo, field.getName(), extInfoV0);
            } else {
                setProperty(taskVo, field, request.getParameter(field.getName()));
            }
        }
    }

    private void setProperty(Object o, Field field, String param) throws InvocationTargetException, IllegalAccessException {
        if (Ft.String.isNotBlank(param)) {
            if (Map.class.isAssignableFrom(field.getType())) {
                Map<String, Object> map = Ft.JSON.parseToMap(param);
                BeanUtils.setProperty(o, field.getName(), map);
            } else {
                BeanUtils.setProperty(o, field.getName(), param);
            }
        }
    }
}
